﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Collections.ObjectModel;

namespace WiFiChannelSpread.GoogleApi
{
    public static class GeolocationApi
    {
        private const int HttpRequestTimeoutMilliseconds = 5000;
        private const string GeolocationApiUrl = "http://www.google.com/loc/json";
        private const string ApplicationHost = "WiFiChannelSpread.CodePlex.com";
        private const string GeolocationApiVersion = "1.1.0";

        public static Location GetGeolocation(Collection<WiFiTower> listOfWiFiTowers, bool includeAddress)
        {
            GeolocationRequest request = CreateGeolocationRequest(includeAddress);
            request.wifi_towers = listOfWiFiTowers;

            string jsonResponse = PostHttpJson(GeolocationApiUrl, Newtonsoft.Json.JsonConvert.SerializeObject(request));
            GeolocationResponse response = Newtonsoft.Json.JsonConvert.DeserializeObject<GeolocationResponse>(jsonResponse);
            if (response == null)
            {
                throw new InvalidOperationException("No response from Google.");
            }

            return response.location;
        }

        public static Location GetGeolocationOfWiFiTower(string macAddress, string ssid, bool includeAddress)
        {
            GeolocationRequest request = CreateGeolocationRequest(includeAddress);
            request.wifi_towers.Add(new WiFiTower { mac_address = macAddress, ssid = ssid });

            string jsonResponse = PostHttpJson(GeolocationApiUrl, Newtonsoft.Json.JsonConvert.SerializeObject(request));
            GeolocationResponse response = Newtonsoft.Json.JsonConvert.DeserializeObject<GeolocationResponse>(jsonResponse);
            if (response == null)
            {
                throw new InvalidOperationException("No response from Google.");
            }

            return response.location;
        }

        private static GeolocationRequest CreateGeolocationRequest(bool includeAddress)
        {
            return new GeolocationRequest
                {
                    host = ApplicationHost,
                    version = GeolocationApiVersion,
                    request_address = includeAddress,
                    wifi_towers = new Collection<WiFiTower>()
                };
        }

        private static string PostHttpJson(string url, string data)
        {
            byte[] postData = Encoding.ASCII.GetBytes(data);

            HttpWebRequest request = CreateWebRequest(url);
            request.Method = "POST";
            request.ContentType = "application/json; charset=utf-8";
            request.Accept = "application/json, text/javascript, */*";
            request.ContentLength = postData.Length;

            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(postData, 0, postData.Length);
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (Stream responseStream = response.GetResponseStream())
            using (StreamReader reader = new StreamReader(responseStream))
            {
                return reader.ReadToEnd();
            }
        }

        private static HttpWebRequest CreateWebRequest(string url)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Timeout = HttpRequestTimeoutMilliseconds;
            return request;
        }

    }
}
